/*
 * Copyright (c) 2020 Samsung Electronics Co., Ltd. All rights reserved.

 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:

 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#ifndef LOTModel_H
#define LOTModel_H

#include <algorithm>
#include <cmath>
#include <cstring>
#include <functional>
#include <memory>
#include <unordered_map>
#include <vector>
#include "varenaalloc.h"
#include "vbezier.h"
#include "vbrush.h"
#include "vinterpolator.h"
#include "vmatrix.h"
#include "vpath.h"
#include "vpoint.h"
#include "vrect.h"

V_USE_NAMESPACE

namespace rlottie {

namespace internal {

using Marker = std::tuple<std::string, int, int>;

using LayerInfo = Marker;

template <typename T>
inline T lerp(const T &start, const T &end, float t)
{
    return start + t * (end - start);
}

namespace model {

enum class MatteType : uint8_t { None = 0, Alpha = 1, AlphaInv, Luma, LumaInv };

enum class BlendMode : uint8_t {
    Normal = 0,
    Multiply = 1,
    Screen = 2,
    OverLay = 3
};

// Color 类用来表示 RGB 颜色模型中的颜色。
class Color {
public:
    // 默认构造函数。
    Color() = default;

    // 构造函数，初始化颜色的红、绿、蓝分量。
    Color(float red, float green, float blue) : r(red), g(green), b(blue) {}

    // toColor 方法将当前颜色转换为 VColor 类型的颜色对象，可以指定 alpha 通道值，默认为完全不透明。
    VColor toColor(float a = 1)
    {
        // 将浮点数形式的颜色分量转换为整数（0-255），并创建 VColor 对象。
        return VColor(uint8_t(255 * r), uint8_t(255 * g), uint8_t(255 * b),
                      uint8_t(255 * a));
    }

    // 操作符重载：+，允许两个 Color 对象相加。
    friend inline Color operator+(const Color &c1, const Color &c2);

    // 操作符重载：-，允许两个 Color 对象相减。
    friend inline Color operator-(const Color &c1, const Color &c2);

public:
    // 颜色的红色分量，默认值为 1.0（即最大强度）。
    float r{1};

    // 颜色的绿色分量，默认值为 1.0（即最大强度）。
    float g{1};

    // 颜色的蓝色分量，默认值为 1.0（即最大强度）。
    float b{1};
};

inline Color operator-(const Color &c1, const Color &c2)
{
    return Color(c1.r - c2.r, c1.g - c2.g, c1.b - c2.b);
}
inline Color operator+(const Color &c1, const Color &c2)
{
    return Color(c1.r + c2.r, c1.g + c2.g, c1.b + c2.b);
}

inline const Color operator*(const Color &c, float m)
{
    return Color(c.r * m, c.g * m, c.b * m);
}

inline const Color operator*(float m, const Color &c)
{
    return Color(c.r * m, c.g * m, c.b * m);
}

// PathData 结构体用来表示路径数据，包括一系列点和路径是否闭合的信息。
struct PathData {
    // mPoints 是一个 VPointF 类型的向量，存储路径上的点。
    std::vector<VPointF> mPoints;

    // mClosed 是一个布尔值，表示路径是否是闭合的，默认为 false。
    bool mClosed = false; /* "c" */

    // reserve 方法预分配内存，以提高后续添加点时的性能。
    void reserve(size_t size) { 
        mPoints.reserve(mPoints.size() + size); 
    }

    // lerp 静态方法用于在两个 PathData 之间执行线性插值，并将结果填充到 VPath 中。
    static void lerp(const PathData &start, const PathData &end, float t,
                     VPath &result)
    {
        result.reset(); // 重置目标路径。

        // 如果任意一个输入路径为空，则直接返回，不做任何操作。
        if (start.mPoints.empty() || end.mPoints.empty()) {
            return;
        }

        // 获取起始和结束路径中较短的那个的大小。
        auto size = std::min(start.mPoints.size(), end.mPoints.size());

        // 预留确切的内存需求，考虑到可能的闭合路径。
        // ptSize = size + 1 (如果路径闭合则加1)
        // elmSize = size/3 (三次贝塞尔曲线的数量) + 1 (移动指令) + 1 (闭合指令)
        result.reserve(size + 1, size / 3 + 2);

        // 插入第一个点，使用线性插值计算中间位置。
        result.moveTo(start.mPoints[0] + t * (end.mPoints[0] - start.mPoints[0]));

        // 遍历每个点对，创建三次贝塞尔曲线段。
        for (size_t i = 1; i < size; i += 3) {
            result.cubicTo(
                start.mPoints[i] + t * (end.mPoints[i] - start.mPoints[i]),
                start.mPoints[i + 1] + t * (end.mPoints[i + 1] - start.mPoints[i + 1]),
                start.mPoints[i + 2] + t * (end.mPoints[i + 2] - start.mPoints[i + 2]));
        }

        // 如果起始路径是闭合的，则闭合结果路径。
        if (start.mClosed) result.close();
    }

    // toPath 方法将当前 PathData 转换为 VPath 对象。
    void toPath(VPath &path) const
    {
        path.reset(); // 重置目标路径。

        if (mPoints.empty()) return; // 如果没有点，则直接返回。

        auto size = mPoints.size();
        auto points = mPoints.data();

        // 预留确切的内存需求，考虑到可能的闭合路径。
        // ptSize = size + 1 (如果路径闭合则加1)
        // elmSize = size/3 (三次贝塞尔曲线的数量) + 1 (移动指令) + 1 (闭合指令)
        path.reserve(size + 1, size / 3 + 2);

        // 移动到第一个点。
        path.moveTo(points[0]);

        // 遍历每个点对，创建三次贝塞尔曲线段。
        for (size_t i = 1; i < size; i += 3) {
            path.cubicTo(points[i], points[i + 1], points[i + 2]);
        }

        // 如果路径是闭合的，则闭合路径。
        if (mClosed) path.close();
    }
};

template <typename T, typename Tag = void>
struct Value {
    T     start_;
    T     end_;
    T     at(float t) const { return lerp(start_, end_, t); }
    float angle(float) const { return 0; }
    void  cache() {}
};

struct Position;

// 模板类Value用于存储和操作具有特定位置（Position）类型的值T。
template <typename T>
struct Value<T, Position> {
    // 成员变量
    T     start_;      // 起始点的位置
    T     end_;        // 结束点的位置
    T     inTangent_;  // 入切线方向（结束端）
    T     outTangent_; // 出切线方向（起始端）
    float length_{0};  // 贝塞尔曲线段的长度，默认初始化为0
    bool  hasTangent_{false}; // 标记是否使用切线来构建贝塞尔曲线，默认不使用

    // 缓存计算结果的方法
    void cache()
    {
        if (hasTangent_) { // 如果启用了切线
            // 更新入出切线的真实位置
            inTangent_ = end_ + inTangent_;
            outTangent_ = start_ + outTangent_;

            // 使用VBezier::fromPoints创建一个贝塞尔曲线，并计算其长度
            length_ = VBezier::fromPoints(start_, outTangent_, inTangent_, end_)
                          .length();

            // 如果计算出的贝塞尔曲线长度为零，则禁用昂贵的路径计算
            if (vIsZero(length_)) {
                hasTangent_ = false;
            }
        }
    }

    // 根据参数t返回贝塞尔曲线上对应位置的点，或线性插值点
    T at(float t) const
    {
        if (hasTangent_) { // 如果启用了切线
            // 创建贝塞尔曲线对象b
            VBezier b =
                VBezier::fromPoints(start_, outTangent_, inTangent_, end_);

            // 返回贝塞尔曲线上距离起点t * length_处的点
            return b.pointAt(b.tAtLength(t * length_, length_));
        }
        // 如果没有启用切线，则直接进行线性插值
        return lerp(start_, end_, t);
    }

    // 根据参数t返回贝塞尔曲线上对应位置的角度，或默认角度0
    float angle(float t) const
    {
        if (hasTangent_) { // 如果启用了切线
            // 创建贝塞尔曲线对象b
            VBezier b =
                VBezier::fromPoints(start_, outTangent_, inTangent_, end_);

            // 返回贝塞尔曲线上距离起点t * length_处的方向角度
            return b.angleAt(b.tAtLength(t * length_, length_));
        }
        // 如果没有启用切线，则返回默认角度0
        return 0;
    }
};
// 模板类 KeyFrames 用于管理一系列的关键帧。
template <typename T, typename Tag>
class KeyFrames {
public:
    // Frame 结构体表示一个关键帧。
    struct Frame {
        // 根据当前帧号返回归一化后的进度（0到1之间）
        float progress(int frameNo) const
        {
            return interpolator_ ? interpolator_->value((frameNo - start_) /
                                                        (end_ - start_))
                                 : 0;
        }

        // 根据当前帧号返回对应的T类型值
        T value(int frameNo) const { 
            return value_.at(progress(frameNo)); 
        }

        // 根据当前帧号返回对应的角度值
        float angle(int frameNo) const
        {
            return value_.angle(progress(frameNo));
        }

        // 起始帧号
        float start_{0};
        // 结束帧号
        float end_{0};
        // 插值器，用于非线性地计算进度
        VInterpolator *interpolator_{nullptr};
        // Value 对象，存储了关键帧的数据和逻辑
        Value<T, Tag> value_;
    };

    // 根据给定的帧号返回对应的T类型值
    T value(int frameNo) const
    {
        // 如果请求的帧号在第一个关键帧之前，返回第一个关键帧的起始值
        if (frames_.front().start_ >= frameNo)
            return frames_.front().value_.start_;

        // 如果请求的帧号在最后一个关键帧之后，返回最后一个关键帧的结束值
        if (frames_.back().end_ <= frameNo) 
            return frames_.back().value_.end_;

        // 遍历所有关键帧，找到与给定帧号相匹配的关键帧并返回其值
        for (const auto &keyFrame : frames_) {
            if (frameNo >= keyFrame.start_ && frameNo < keyFrame.end_)
                return keyFrame.value(frameNo);
        }
        // 如果没有匹配的关键帧，则返回默认构造的T类型实例
        return {};
    }

    // 根据给定的帧号返回对应的角度值
    float angle(int frameNo) const
    {
        // 如果帧号不在关键帧范围内，则返回0
        if ((frames_.front().start_ >= frameNo) ||
            (frames_.back().end_ <= frameNo))
            return 0;

        // 查找与给定帧号相匹配的关键帧，并返回其角度值
        for (const auto &frame : frames_) {
            if (frameNo >= frame.start_ && frameNo < frame.end_)
                return frame.angle(frameNo);
        }
        // 如果没有匹配的关键帧，则返回0
        return 0;
    }

    // 判断两个帧之间的变化情况
    bool changed(int prevFrame, int curFrame) const
    {
        auto first = frames_.front().start_;
        auto last = frames_.back().end_;

        // 如果变化发生在所有关键帧之外，则返回false
        return !((first > prevFrame && first > curFrame) ||
                 (last < prevFrame && last < curFrame));
    }

    // 缓存所有关键帧中的贝塞尔曲线数据
    void cache()
    {
        for (auto &e : frames_) 
            e.value_.cache();
    }

public:
    // 存储所有关键帧的容器
    std::vector<Frame> frames_;
};
// Property 模板类用来表示一个属性，它可以是一个静态值或者一段动画。
template <typename T, typename Tag = void>
class Property {
public:
    // 定义动画类型为 KeyFrames<T, Tag>
    using Animation = KeyFrames<T, Tag>;

    // 默认构造函数，初始化为静态值状态
    Property() { construct(impl_.value_, {}); }

    // 构造函数，接受一个 T 类型的值并初始化为静态值状态
    explicit Property(T value) { construct(impl_.value_, std::move(value)); }

    // 获取动画引用（常量版本）
    const Animation &animation() const { return *(impl_.animation_.get()); }
    
    // 获取当前静态值的引用（常量版本）
    const T &value() const { return impl_.value_; }

    // 获取可修改的动画引用，如果当前是静态值状态，则先销毁静态值并转换为动画状态
    Animation &animation()
    {
        if (isValue_) {
            destroy();
            construct(impl_.animation_, std::make_unique<Animation>());
            isValue_ = false;
        }
        return *(impl_.animation_.get());
    }

    // 获取可修改的静态值引用，要求当前必须是静态值状态
    T &value()
    {
        assert(isValue_);
        return impl_.value_;
    }

    // 移动构造函数，负责处理从另一个 Property 实例移动资源过来
    Property(Property &&other) noexcept
    {
        if (!other.isValue_) {
            construct(impl_.animation_, std::move(other.impl_.animation_));
            isValue_ = false;
        } else {
            construct(impl_.value_, std::move(other.impl_.value_));
            isValue_ = true;
        }
    }

    // 禁用拷贝构造和赋值操作符以防止浅拷贝带来的问题
    Property(const Property &) = delete;
    Property &operator=(const Property &) = delete;
    Property &operator=(Property &&) = delete;

    // 析构函数，负责清理资源
    ~Property() { destroy(); }

    // 判断属性是否为静态值状态
    bool isStatic() const { return isValue_; }

    // 根据帧号返回对应的 T 类型值，考虑静态值和动画两种情况
    T value(int frameNo) const
    {
        return isStatic() ? value() : animation().value(frameNo);
    }

    // 特化函数，仅适用于 T=PathData 的情况，将结果写入 VPath 对象中
    template <typename forT = PathData>
    auto value(int frameNo, VPath &path) const ->
        typename std::enable_if_t<std::is_same<T, forT>::value, void>
    {
        if (isStatic()) {
            value().toPath(path);
        } else {
            const auto &vec = animation().frames_;
            if (vec.front().start_ >= frameNo)
                return vec.front().value_.start_.toPath(path);
            if (vec.back().end_ <= frameNo)
                return vec.back().value_.end_.toPath(path);

            for (const auto &keyFrame : vec) {
                if (frameNo >= keyFrame.start_ && frameNo < keyFrame.end_) {
                    T::lerp(keyFrame.value_.start_, keyFrame.value_.end_,
                            keyFrame.progress(frameNo), path);
                }
            }
        }
    }

    // 根据帧号返回对应的角度值，只对动画有效
    float angle(int frameNo) const
    {
        return isStatic() ? 0 : animation().angle(frameNo);
    }

    // 判断两个帧之间是否有变化发生，只对动画有效
    bool changed(int prevFrame, int curFrame) const
    {
        return isStatic() ? false : animation().changed(prevFrame, curFrame);
    }

    // 缓存动画中的所有关键帧数据
    void cache()
    {
        if (!isStatic()) animation().cache();
    }

private:
    // 辅助函数，用于在联合体内构造对象
    template <typename Tp>
    void construct(Tp &member, Tp &&val)
    {
        new (&member) Tp(std::move(val));
    }

    // 销毁联合体内的当前对象
    void destroy()
    {
        if (isValue_) {
            impl_.value_.~T();
        } else {
            using std::unique_ptr;
            impl_.animation_.~unique_ptr<Animation>();
        }
    }

    // 联合体 details 用于存储 T 类型的值或者 Animation 类型的指针
    union details {
        std::unique_ptr<Animation> animation_;
        T                          value_;
        details(){};
        details(const details &) = delete;
        details(details &&) = delete;
        details &operator=(details &&) = delete;
        details &operator=(const details &) = delete;
        ~details() noexcept {};
    } impl_;

    // 标记当前是静态值还是动画状态
    bool isValue_{true};
};

class Path;
struct PathData;
struct Dash {
    std::vector<Property<float>> mData;
    bool                         empty() const { return mData.empty(); }
    size_t                       size() const { return mData.size(); }
    bool                         isStatic() const
    {
        for (const auto &elm : mData)
            if (!elm.isStatic()) return false;
        return true;
    }
    void getDashInfo(int frameNo, std::vector<float> &result) const;
};

class Mask {
public:
    enum class Mode { None, Add, Substarct, Intersect, Difference };
    float opacity(int frameNo) const
    {
        return mOpacity.value(frameNo) / 100.0f;
    }
    bool isStatic() const { return mIsStatic; }

public:
    Property<PathData> mShape;
    Property<float>    mOpacity{100};
    bool               mInv{false};
    bool               mIsStatic{true};
    Mask::Mode         mMode;
};

class Object {
public:
    // 定义对象的类型枚举
    enum class Type : unsigned char {
        Composition = 1,  // 合成对象
        Layer,            // 图层
        Group,            // 组
        Transform,        // 变换
        Fill,             // 填充
        Stroke,           // 描边
        GFill,            // 渐变填充
        GStroke,          // 渐变描边
        Rect,             // 矩形
        Ellipse,          // 椭圆
        Path,             // 路径
        Polystar,         // 多角星形
        Trim,             // 修剪
        Repeater,         // 重复器
        RoundedCorner     // 圆角
    };

    // 构造函数，初始化对象类型和其他默认属性
    explicit Object(Object::Type type) : mPtr(nullptr)
    {
        mData._type = type;
        mData._static = true;      // 默认是静态的
        mData._shortString = true; // 默认使用短字符串存储名称
        mData._hidden = false;     // 默认不隐藏
    }

    // 析构函数，确保释放动态分配的内存
    ~Object() noexcept
    {
        if (!shortString() && mPtr) free(mPtr);
    }

    // 禁用拷贝构造和赋值操作符以防止浅拷贝带来的问题
    Object(const Object &) = delete;
    Object &operator=(const Object &) = delete;

    // 设置/获取对象是否为静态的方法
    void setStatic(bool value) { mData._static = value; }
    bool isStatic() const { return mData._static; }

    // 设置/获取对象是否隐藏的方法
    bool hidden() const { return mData._hidden; }
    void setHidden(bool value) { mData._hidden = value; }

    // 设置/获取对象类型的方
    void setType(Object::Type type) { mData._type = type; }
    Object::Type type() const { return mData._type; }

    // 设置对象名称的方法
    void setName(const char *name)
    {
        if (name) {
            auto len = strlen(name);
            if (len < maxShortStringLength) {
                setShortString(true); // 使用内部缓冲区
                strncpy(mData._buffer, name, len + 1);
            } else {
                setShortString(false); // 使用动态分配的内存
                mPtr = strdup(name);   // 注意：strdup在某些平台上可能不是C++标准的一部分
            }
        }
    }

    // 获取对象名称的方法
    const char *name() const { return shortString() ? mData._buffer : mPtr; }

private:
    static constexpr unsigned char maxShortStringLength = 14; // 内部缓冲区最大长度

    // 设置/获取对象名称是否使用短字符串的方法
    void setShortString(bool value) { mData._shortString = value; }
    bool shortString() const { return mData._shortString; }

    // 结构体 Data 用于存储对象的元数据
    struct Data {
        char         _buffer[maxShortStringLength]; // 用于存储短字符串的缓冲区
        Object::Type _type;                         // 对象类型
        bool         _static : 1;                   // 是否静态
        bool         _hidden : 1;                   // 是否隐藏
        bool         _shortString : 1;              // 是否使用短字符串
    };

    // 联合体用于存储对象名称，要么是在内部缓冲区中，要么是指向外部分配的内存的指针
    union {
        Data  mData;  // 存储对象的元数据
        char *mPtr{nullptr}; // 如果名称过长，则指向动态分配的内存
    };
};

struct Asset {
    // 定义资源类型枚举
    enum class Type : unsigned char { Precomp, Image, Char };

    // 获取/设置资源是否为静态的方法
    bool isStatic() const { return mStatic; }
    void setStatic(bool value) { mStatic = value; }

    // 获取位图数据的方法
    VBitmap bitmap() const { return mBitmap; }

    // 加载图像数据的方法
    void loadImageData(std::string data);

    // 加载图像路径的方法
    void loadImagePath(std::string Path);

    // 资源类型，默认是预合成
    Type mAssetType{Type::Precomp};

    // 标记资源是否为静态，默认为true
    bool mStatic{true};

    // 资源引用ID
    std::string mRefId;

    // 层列表，指向Object对象的指针向量
    std::vector<Object *> mLayers;

    // 图像资源的数据成员
    int     mWidth{0};      // 图像宽度
    int     mHeight{0};     // 图像高度
    VBitmap mBitmap;        // 位图对象
};

class Layer;

class Composition : public Object {
public:
    Composition() : Object(Object::Type::Composition) {}
    std::vector<LayerInfo>     layerInfoList() const;
    const std::vector<Marker> &markers() const { return mMarkers; }
    double                     duration() const
    {
        return frameDuration() / frameRate();  // in second
    }
    size_t frameAtPos(double pos) const
    {
        if (pos < 0) pos = 0;
        if (pos > 1) pos = 1;
        return size_t(round(pos * frameDuration()));
    }
    long frameAtTime(double timeInSec) const
    {
        return long(frameAtPos(timeInSec / duration()));
    }
    size_t totalFrame() const { return mEndFrame - mStartFrame + 1; }
    long   frameDuration() const { return mEndFrame - mStartFrame; }
    float  frameRate() const { return mFrameRate; }
    size_t startFrame() const { return mStartFrame; }
    size_t endFrame() const { return mEndFrame; }
    VSize  size() const { return mSize; }
    void   processRepeaterObjects();
    void   updateStats();

public:
    struct Stats {
        uint16_t precompLayerCount{0};
        uint16_t solidLayerCount{0};
        uint16_t shapeLayerCount{0};
        uint16_t imageLayerCount{0};
        uint16_t nullLayerCount{0};
    };

public:
    std::string                              mVersion;
    VSize                                    mSize;
    long                                     mStartFrame{0};
    long                                     mEndFrame{0};
    float                                    mFrameRate{60};
    BlendMode                                mBlendMode{BlendMode::Normal};
    Layer *                                  mRootLayer{nullptr};
    std::unordered_map<std::string, Asset *> mAssets;

    std::vector<Marker> mMarkers;
    VArenaAlloc         mArenaAlloc{2048};
    Stats               mStats;
};

// Transform 类继承自 Object 类，用于表示一个可以进行变换的对象。
class Transform : public Object {
public:
    // 内部 Data 结构体，保存变换数据。
    struct Data {
        // 内嵌结构体 Extra 用于存储额外的3D变换属性。
        struct Extra {
            Property<float> m3DRx{0};   // 3D X轴旋转角度，默认为0
            Property<float> m3DRy{0};   // 3D Y轴旋转角度，默认为0
            Property<float> m3DRz{0};   // 3D Z轴旋转角度，默认为0
            Property<float> mSeparateX{0}; // 分离变换的X分量，默认为0
            Property<float> mSeparateY{0}; // 分离变换的Y分量，默认为0
            bool            mSeparate{false}; // 标记是否使用分离变换，默认不使用
            bool            m3DData{false};   // 标记是否包含3D数据，默认不包含
        };

        // 根据指定帧号计算变换矩阵，可选参数 autoOrient 控制是否自动调整方向。
        VMatrix matrix(int frameNo, bool autoOrient = false) const;

        // 获取指定帧号的透明度值，范围从0到1。
        float opacity(int frameNo) const {
            return mOpacity.value(frameNo) / 100.0f;
        }

        // 如果没有创建Extra数据，则创建之。
        void createExtraData() {
            if (!mExtra) mExtra = std::make_unique<Extra>();
        }

        // 各种变换属性，使用Property模板类管理这些属性随时间的变化。
        Property<float>             mRotation{0};       // 2D旋转角度，默认为0
        Property<VPointF>           mScale{{100, 100}}; // 缩放比例，默认为100%
        Property<VPointF, Position> mPosition;          // 位置，默认构造函数决定
        Property<VPointF>           mAnchor;            // 锚点，默认构造函数决定
        Property<float>             mOpacity{100};      // 不透明度，默认为完全不透明

        // 指向Extra数据的智能指针，允许动态分配和释放内存。
        std::unique_ptr<Extra>      mExtra;
    };

    // 构造函数初始化类型为 Transform 的Object。
    Transform() : Object(Object::Type::Transform) {}

    // 设置变换数据，并标记此变换是否静态。
    void set(Transform::Data *data, bool staticFlag) {
        setStatic(staticFlag);
        if (isStatic()) {
            // 如果是静态变换，则直接初始化静态数据成员。
            new (&impl.mStaticData)
                StaticData(data->matrix(0), data->opacity(0));
        } else {
            // 如果不是静态变换，则保存动态数据指针。
            impl.mData = data;
        }
    }

    // 获取指定帧号的变换矩阵。
    VMatrix matrix(int frameNo, bool autoOrient = false) const {
        if (isStatic()) return impl.mStaticData.mMatrix;
        return impl.mData->matrix(frameNo, autoOrient);
    }

    // 获取指定帧号的透明度。
    float opacity(int frameNo) const {
        if (isStatic()) return impl.mStaticData.mOpacity;
        return impl.mData->opacity(frameNo);
    }

    // 禁用复制构造函数和赋值操作符，防止浅拷贝。
    Transform(const Transform &) = delete;
    Transform(Transform &&) = delete;
    Transform &operator=(Transform &) = delete;
    Transform &operator=(Transform &&) = delete;

    // 析构函数调用 destroy 方法清理资源。
    ~Transform() noexcept { destroy(); }

private:
    // 清理资源的方法，根据是否静态选择清理策略。
    void destroy() {
        if (isStatic()) {
            impl.mStaticData.~StaticData();
        }
    }

    // StaticData 结构体用于保存静态变换的数据。
    struct StaticData {
        StaticData(VMatrix &&m, float opacity)
            : mOpacity(opacity), mMatrix(std::move(m)) {}
        float   mOpacity; // 静态透明度
        VMatrix mMatrix;  // 静态变换矩阵
    };

    // Union details 用于在静态和动态数据之间共享同一块内存。
    union details {
        Data *     mData{nullptr};      // 动态数据指针
        StaticData mStaticData;         // 静态数据成员

        // 默认构造函数和禁止复制/移动语义。
        details(){};
        details(const details &) = delete;
        details(details &&) = delete;
        details &operator=(details &&) = delete;
        details &operator=(const details &) = delete;

        // 析构函数，确保正确清理Union内的成员。
        ~details() noexcept {};
    } impl; // Union 实例化为 impl 成员变量。
};

class Group : public Object {
public:
    Group() : Object(Object::Type::Group) {}
    explicit Group(Object::Type type) : Object(type) {}

public:
    std::vector<Object *> mChildren;
    Transform *           mTransform{nullptr};
};

class Layer : public Group {
public:
    enum class Type : uint8_t {
        Precomp = 0,
        Solid = 1,
        Image = 2,
        Null = 3,
        Shape = 4,
        Text = 5
    };
    Layer() : Group(Object::Type::Layer) {}
    bool    hasRoundedCorner() const noexcept { return mHasRoundedCorner; }
    bool    hasPathOperator() const noexcept { return mHasPathOperator; }
    bool    hasGradient() const noexcept { return mHasGradient; }
    bool    hasMask() const noexcept { return mHasMask; }
    bool    hasRepeater() const noexcept { return mHasRepeater; }
    int     id() const noexcept { return mId; }
    int     parentId() const noexcept { return mParentId; }
    bool    hasParent() const noexcept { return mParentId != -1; }
    int     inFrame() const noexcept { return mInFrame; }
    int     outFrame() const noexcept { return mOutFrame; }
    int     startFrame() const noexcept { return mStartFrame; }
    Color   solidColor() const noexcept
    {
        return mExtra ? mExtra->mSolidColor : Color();
    }
    bool    autoOrient() const noexcept { return mAutoOrient; }
    int     timeRemap(int frameNo) const;
    VSize   layerSize() const { return mLayerSize; }
    bool    precompLayer() const { return mLayerType == Type::Precomp; }
    VMatrix matrix(int frameNo) const
    {
        return mTransform ? mTransform->matrix(frameNo, autoOrient())
                          : VMatrix{};
    }
    float opacity(int frameNo) const
    {
        return mTransform ? mTransform->opacity(frameNo) : 1.0f;
    }
    Asset *asset() const { return mExtra ? mExtra->mAsset : nullptr; }
    struct Extra {
        Color               mSolidColor;
        std::string         mPreCompRefId;
        Property<float>     mTimeRemap; /* "tm" */
        Composition *       mCompRef{nullptr};
        Asset *             mAsset{nullptr};
        std::vector<Mask *> mMasks;
    };

    Layer::Extra *extra()
    {
        if (!mExtra) mExtra = std::make_unique<Layer::Extra>();
        return mExtra.get();
    }

public:
    MatteType mMatteType{MatteType::None};
    Type      mLayerType{Layer::Type::Null};
    BlendMode mBlendMode{BlendMode::Normal};
    bool      mHasRoundedCorner{false};
    bool      mHasPathOperator{false};
    bool      mHasMask{false};
    bool      mHasRepeater{false};
    bool      mHasGradient{false};
    bool      mAutoOrient{false};
    VSize     mLayerSize;
    int       mParentId{-1};  // Lottie the id of the parent in the composition
    int       mId{-1};        // Lottie the group id  used for parenting.
    float     mTimeStreatch{1.0f};
    int       mInFrame{0};
    int       mOutFrame{0};
    int       mStartFrame{0};
    std::unique_ptr<Extra> mExtra{nullptr};
};

/**
 * TimeRemap has the value in time domain(in sec)
 * To get the proper mapping first we get the mapped time at the current frame
 * Number then we need to convert mapped time to frame number using the
 * composition time line Ex: at frame 10 the mappend time is 0.5(500 ms) which
 * will be convert to frame number 30 if the frame rate is 60. or will result to
 * frame number 15 if the frame rate is 30.
 */
inline int Layer::timeRemap(int frameNo) const
{
    /*
     * only consider startFrame() when there is no timeRemap.
     * when a layer has timeremap bodymovin updates the startFrame()
     * of all child layer so we don't have to take care of it.
     */
    if (!mExtra || mExtra->mTimeRemap.isStatic())
        frameNo = frameNo - startFrame();
    else
        frameNo =
            mExtra->mCompRef->frameAtTime(mExtra->mTimeRemap.value(frameNo));
    /* Apply time streatch if it has any.
     * Time streatch is just a factor by which the animation will speedup or
     * slow down with respect to the overal animation. Time streach factor is
     * already applied to the layers inFrame and outFrame.
     * @TODO need to find out if timestreatch also affects the in and out frame
     * of the child layers or not. */
    return int(frameNo / mTimeStreatch);
}

class Stroke : public Object {
public:
    // 构造函数初始化类型为 Stroke 的Object。
    Stroke() : Object(Object::Type::Stroke) {}

    // 获取指定帧号的颜色值。
    Color color(int frameNo) const { 
        return mColor.value(frameNo); 
    }

    // 获取指定帧号的透明度值，范围从0到1。
    float opacity(int frameNo) const {
        return mOpacity.value(frameNo) / 100.0f;
    }

    // 获取指定帧号的线条宽度。
    float strokeWidth(int frameNo) const { 
        return mWidth.value(frameNo); 
    }

    // 获取线条端点样式。
    CapStyle capStyle() const { 
        return mCapStyle; 
    }

    // 获取线条连接样式。
    JoinStyle joinStyle() const { 
        return mJoinStyle; 
    }

    // 获取斜接限制（miter limit），用于确定在连接样式为斜接时的角度限制。
    float miterLimit() const { 
        return mMiterLimit; 
    }

    // 检查是否有虚线信息。
    bool hasDashInfo() const { 
        return !mDash.empty(); 
    }

    // 获取指定帧号的虚线信息，并存储到传入的结果向量中。
    void getDashInfo(int frameNo, std::vector<float> &result) const {
        return mDash.getDashInfo(frameNo, result);
    }

public: // 成员变量，通常成员变量应该定义为private或protected，这里可能是为了简化代码而公开。
    Property<Color> mColor;                       // 颜色属性，默认构造函数决定初始值 /* "c" */
    Property<float> mOpacity{100};                // 不透明度属性，默认完全不透明 /* "o" */
    Property<float> mWidth{0};                    // 线条宽度属性，默认宽度为0 /* "w" */
    CapStyle        mCapStyle{CapStyle::Flat};    // 端点样式，默认为平直端点 /* "lc" */
    JoinStyle       mJoinStyle{JoinStyle::Miter}; // 连接样式，默认为斜接 /* "lj" */
    float           mMiterLimit{0};               // 斜接限制，默认值为0 /* "ml" */
    Dash            mDash;                        // 虚线模式，默认构造函数决定初始值
    bool            mEnabled{true};               // 是否启用，默认启用 /* "fillEnabled" */
};
// Gradient 类继承自 Object 类，代表一个图形对象的渐变填充。
class Gradient : public Object {
public:
    // Data 类是 Gradient 的内部类，用来存储与渐变相关的数据。
    class Data {
    public:
        // 重载 + 操作符，允许两个 Gradient::Data 对象相加。
        friend inline Gradient::Data operator+(const Gradient::Data &g1,
                                               const Gradient::Data &g2);
        // 重载 - 操作符，允许两个 Gradient::Data 对象相减。
        friend inline Gradient::Data operator-(const Gradient::Data &g1,
                                               const Gradient::Data &g2);
        // 重载 * 操作符，允许一个浮点数乘以一个 Gradient::Data 对象。
        friend inline Gradient::Data operator*(float                 m,
                                               const Gradient::Data &g);

    public:
        // mGradient 是一个浮点数向量，可能用于存储渐变的颜色值或其它相关数据。
        std::vector<float> mGradient;
    };

    // 构造函数，通过传递类型来初始化 Gradient 对象。
    explicit Gradient(Object::Type type) : Object(type) {}

    // opacity 方法返回指定帧号时的透明度值（0.0 到 1.0），基于 mOpacity 属性。
    inline float opacity(int frameNo) const
    {
        return mOpacity.value(frameNo) / 100.0f;
    }

    // update 方法更新渐变对象到指定帧号的状态。
    void update(std::unique_ptr<VGradient> &grad, int frameNo);

private:
    // populate 方法填充颜色停止点到 stops 容器中，对应于指定帧号。
    void populate(VGradientStops &stops, int frameNo);
    
    // getOpacityAtPosition 方法根据位置计算不透明度值。
    float getOpacityAtPosition(float *opacities, size_t opacityArraySize, float position);

public:
    // mGradientType 表示渐变的类型：线性 (1) 或径向 (2)。 "t"
    int                      mGradientType{1};    

    // mStartPoint 表示渐变的起点位置。  "s"
    Property<VPointF>        mStartPoint;         

    // mEndPoint 表示渐变的终点位置。  "e"
    Property<VPointF>        mEndPoint;           

    // mHighlightLength 可能表示高亮部分的长度。 "h"
    Property<float>          mHighlightLength{0}; 

    // mHighlightAngle 可能表示高亮部分的角度。 "a"
    Property<float>          mHighlightAngle{0};  

    // mOpacity 表示渐变整体的透明度，初始值为 100% 不透明。 "o"
    Property<float>          mOpacity{100};       

    // mGradient 是一个 Property<Gradient::Data> 类型的对象，可能存储了渐变的数据。 "g"
    Property<Gradient::Data> mGradient;           

    // mColorPoints 可能表示渐变中使用的颜色点数量。
    int                      mColorPoints{-1};

    // mEnabled 表示该渐变是否启用。
    bool                     mEnabled{true};      
};

// GradientStroke 类扩展了 Gradient 类，以表示具有渐变填充的描边。
class GradientStroke : public Gradient {
public:
    // 构造函数初始化一个 GradientStroke 对象，并指定其类型为 GStroke。
    GradientStroke() : Gradient(Object::Type::GStroke) {}

    // width 方法返回指定帧号时的描边宽度。
    float width(int frameNo) const { return mWidth.value(frameNo); }

    // capStyle 方法返回描边端点的样式。
    CapStyle capStyle() const { return mCapStyle; }

    // joinStyle 方法返回描边转角的样式。
    JoinStyle joinStyle() const { return mJoinStyle; }

    // miterLimit 方法返回斜接限制值，用于确定何时将尖角转换为圆角。
    float miterLimit() const { return mMiterLimit; }

    // hasDashInfo 方法检查描边是否有虚线信息。
    bool hasDashInfo() const { return !mDash.empty(); }

    // getDashInfo 方法根据提供的帧号填充结果向量，包含当前的虚线模式信息。
    void getDashInfo(int frameNo, std::vector<float> &result) const
    {
        return mDash.getDashInfo(frameNo, result);
    }

public:
    // mWidth 是 Property<float> 类型的对象，表示描边的宽度。
    Property<float> mWidth;                       /* "w" */

    // mCapStyle 表示描边端点的样式，默认为平直端点。
    CapStyle        mCapStyle{CapStyle::Flat};    /* "lc" */

    // mJoinStyle 表示描边转角的样式，默认为斜接。
    JoinStyle       mJoinStyle{JoinStyle::Miter}; /* "lj" */

    // mMiterLimit 表示斜接限制值，默认为 0。
    float           mMiterLimit{0};               /* "ml" */

    // mDash 包含有关虚线模式的信息。
    Dash            mDash;
};

class GradientFill : public Gradient {
public:
    GradientFill() : Gradient(Object::Type::GFill) {}
    FillRule fillRule() const { return mFillRule; }

public:
    FillRule mFillRule{FillRule::Winding}; /* "r" */
};

class Fill : public Object {
public:
    Fill() : Object(Object::Type::Fill) {}
    Color color(int frameNo) const { return mColor.value(frameNo); }
    float opacity(int frameNo) const
    {
        return mOpacity.value(frameNo) / 100.0f;
    }
    FillRule fillRule() const { return mFillRule; }

public:
    FillRule        mFillRule{FillRule::Winding}; /* "r" */
    bool            mEnabled{true};               /* "fillEnabled" */
    Property<Color> mColor;                       /* "c" */
    Property<float> mOpacity{100};                /* "o" */
};

class Shape : public Object {
public:
    explicit Shape(Object::Type type) : Object(type) {}
    VPath::Direction direction()
    {
        return (mDirection == 3) ? VPath::Direction::CCW : VPath::Direction::CW;
    }

public:
    int mDirection{1};
};

class Path : public Shape {
public:
    Path() : Shape(Object::Type::Path) {}

public:
    Property<PathData> mShape;
};

class RoundedCorner : public Object {
public:
    RoundedCorner() : Object(Object::Type::RoundedCorner) {}
    float radius(int frameNo) const { return mRadius.value(frameNo);}
public:
    Property<float>   mRadius{0};
};

class Rect : public Shape {
public:
    Rect() : Shape(Object::Type::Rect) {}
    float roundness(int frameNo)
    {
        return mRoundedCorner ? mRoundedCorner->radius(frameNo) :
                                mRound.value(frameNo);
    }

    bool roundnessChanged(int prevFrame, int curFrame)
    {
        return mRoundedCorner ? mRoundedCorner->mRadius.changed(prevFrame, curFrame) :
                        mRound.changed(prevFrame, curFrame);
    }
public:
    RoundedCorner*    mRoundedCorner{nullptr};
    Property<VPointF> mPos;
    Property<VPointF> mSize;
    Property<float>   mRound{0};
};

class Ellipse : public Shape {
public:
    Ellipse() : Shape(Object::Type::Ellipse) {}

public:
    Property<VPointF> mPos;
    Property<VPointF> mSize;
};

class Polystar : public Shape {
public:
    enum class PolyType { Star = 1, Polygon = 2 };
    Polystar() : Shape(Object::Type::Polystar) {}

public:
    Polystar::PolyType mPolyType{PolyType::Polygon};
    Property<VPointF>  mPos;
    Property<float>    mPointCount{0};
    Property<float>    mInnerRadius{0};
    Property<float>    mOuterRadius{0};
    Property<float>    mInnerRoundness{0};
    Property<float>    mOuterRoundness{0};
    Property<float>    mRotation{0};
};

// Repeater 类扩展了 Object 类，以表示一个能够复制其内部内容并对其应用变换的对象。
class Repeater : public Object {
public:
    // Transform 结构体包含与变换相关的属性和方法。
    struct Transform {
        // matrix 方法返回指定帧号时的变换矩阵，根据提供的乘数调整。
        VMatrix matrix(int frameNo, float multiplier) const;

        // startOpacity 方法返回指定帧号时的起始不透明度值（0.0 到 1.0）。
        float startOpacity(int frameNo) const {
            return mStartOpacity.value(frameNo) / 100;
        }

        // endOpacity 方法返回指定帧号时的结束不透明度值（0.0 到 1.0）。
        float endOpacity(int frameNo) const {
            return mEndOpacity.value(frameNo) / 100;
        }

        // isStatic 方法检查所有属性是否为静态（即不随时间变化）。
        bool isStatic() const {
            return mRotation.isStatic() && mScale.isStatic() &&
                   mPosition.isStatic() && mAnchor.isStatic() &&
                   mStartOpacity.isStatic() && mEndOpacity.isStatic();
        }

        // mRotation 属性表示旋转角度，默认为 0 度。
        Property<float> mRotation{0};       /* "r" */

        // mScale 属性表示缩放比例，默认为 100%。
        Property<VPointF> mScale{{100, 100}}; /* "s" */

        // mPosition 属性表示位置偏移。
        Property<VPointF> mPosition;          /* "p" */

        // mAnchor 属性表示锚点位置。
        Property<VPointF> mAnchor;            /* "a" */

        // mStartOpacity 属性表示开始时不透明度，默认为 100% 不透明。
        Property<float> mStartOpacity{100};   /* "so" */

        // mEndOpacity 属性表示结束时不透明度，默认为 100% 不透明。
        Property<float> mEndOpacity{100};     /* "eo" */
    };

    // 构造函数初始化 Repeater 对象，并设置其类型为 Repeater。
    Repeater() : Object(Object::Type::Repeater) {}

    // content 方法返回当前 Repeater 的内容 Group 指针。
    Group* content() const { return mContent ? mContent : nullptr; }

    // setContent 方法设置 Repeater 的内容 Group。
    void setContent(Group* content) { mContent = content; }

    // maxCopies 方法返回可以创建的最大副本数量。
    int maxCopies() const { return static_cast<int>(mMaxCopies); }

    // copies 方法返回指定帧号时的副本数量。
    float copies(int frameNo) const { return mCopies.value(frameNo); }

    // offset 方法返回指定帧号时的副本间偏移量。
    float offset(int frameNo) const { return mOffset.value(frameNo); }

    // processed 方法返回 Repeater 是否已经被处理过。
    bool processed() const { return mProcessed; }

    // markProcessed 方法标记 Repeater 已被处理。
    void markProcessed() { mProcessed = true; }

public:
    // mContent 是一个指针，指向 Repeater 内部的内容 Group。
    Group* mContent{nullptr};

    // mTransform 包含与 Repeater 相关的所有变换信息。
    Transform mTransform;

    // mCopies 是一个 Property<float> 类型的对象，表示副本的数量。
    Property<float> mCopies{0};

    // mOffset 是一个 Property<float> 类型的对象，表示副本间的偏移量。
    Property<float> mOffset{0};

    // mMaxCopies 表示最大副本数量。
    float mMaxCopies{0.0};

    // mProcessed 标记 Repeater 是否已经完成处理。
    bool mProcessed{false};
};

// Trim 类扩展了 Object 类，以表示一个能够修剪路径的对象。
class Trim : public Object {
public:
    // Segment 结构体用来存储路径修剪的起始和结束位置。
    struct Segment {
        float start{0}; // 路径修剪的起始位置，默认为 0。
        float end{0};   // 路径修剪的结束位置，默认为 0。
        
        Segment() = default; // 默认构造函数。
        explicit Segment(float s, float e) : start(s), end(e) {} // 构造函数，初始化 start 和 end。
    };

    // TrimType 枚举定义了修剪类型的两种模式：同时修剪 (Simultaneously) 和单独修剪 (Individually)。
    enum class TrimType { Simultaneously, Individually };

    // 构造函数初始化 Trim 对象，并设置其类型为 Trim。
    Trim() : Object(Object::Type::Trim) {}

    // updateTrimStartValue 方法更新修剪的起始值。
    void updateTrimStartValue(float start)
    {
        mStart.value() = start;
    }

    // updateTrimEndValue 方法根据提供的 VPointF 更新所有关键帧的修剪结束值。
    void updateTrimEndValue(VPointF pos)
    {
        for (auto &keyFrame : mEnd.animation().frames_) {
            keyFrame.value_.start_ = pos.x();
            keyFrame.value_.end_ = pos.y();
        }
    }

    // segment 方法计算并返回指定帧号时的修剪段。
    // 如果 start > end，则路径被修剪为一个环（两个段）。
    // 如果 start < end，则路径被修剪为非环形（一个段）。
    // 如果没有偏移，则没有环形。
    Segment segment(int frameNo) const
    {
        // 获取当前帧的起始、结束和偏移值，并将它们转换为 0 到 1 的范围。
        float start = mStart.value(frameNo) / 100.0f;
        float end = mEnd.value(frameNo) / 100.0f;
        float offset = std::fmod(mOffset.value(frameNo), 360.0f) / 360.0f;

        // 计算起始和结束之间的差异。
        float diff = std::abs(start - end);
        if (vCompare(diff, 0.0f)) return Segment(0, 0); // 如果差值为 0，返回空段。
        if (vCompare(diff, 1.0f)) return Segment(0, 1); // 如果差值为 1，返回完整段。

        // 根据是否有偏移处理不同的情况。
        if (offset > 0) {
            start += offset;
            end += offset;
            if (start <= 1 && end <= 1) {
                return noloop(start, end); // 没有超过范围的情况。
            } else if (start > 1 && end > 1) {
                return noloop(start - 1, end - 1); // 超过范围后的修正。
            } else {
                return (start > 1) ? loop(start - 1, end) : loop(start, end - 1); // 环形情况。
            }
        } else {
            start += offset;
            end += offset;
            if (start >= 0 && end >= 0) {
                return noloop(start, end); // 没有低于 0 的情况。
            } else if (start < 0 && end < 0) {
                return noloop(1 + start, 1 + end); // 低于 0 后的修正。
            } else {
                return (start < 0) ? loop(1 + start, end) : loop(start, 1 + end); // 环形情况。
            }
        }
    }

    // type 方法返回当前的修剪类型。
    Trim::TrimType type() const { return mTrimType; }

private:
    // noloop 方法确保不形成环形修剪段，并返回修剪段。
    Segment noloop(float start, float end) const
    {
        assert(start >= 0);
        assert(end >= 0);
        Segment s;
        s.start = std::min(start, end);
        s.end = std::max(start, end);
        return s;
    }

    // loop 方法确保形成环形修剪段，并返回修剪段。
    Segment loop(float start, float end) const
    {
        assert(start >= 0);
        assert(end >= 0);
        Segment s;
        s.start = std::max(start, end);
        s.end = std::min(start, end);
        return s;
    }

public:
    // mStart 属性表示修剪的起始位置，默认为 0%。
    Property<float> mStart{0};

    // mEnd 属性表示修剪的结束位置，默认为 0%。
    Property<float> mEnd{0};

    // mOffset 属性表示修剪的偏移量，默认为 0。
    Property<float> mOffset{0};

    // mTrimType 属性表示修剪的类型，默认为同时修剪。
    Trim::TrimType mTrimType{TrimType::Simultaneously};
};

// 操作符重载函数，用于 Gradient::Data 类型的加法。
inline Gradient::Data operator+(const Gradient::Data &g1,
                                const Gradient::Data &g2)
{
    // 如果两个渐变的数据长度不匹配，直接返回 g1。
    if (g1.mGradient.size() != g2.mGradient.size()) return g1;

    // 创建一个新的 Gradient::Data 对象来存储结果。
    Gradient::Data newG;
    
    // 将 g1 的 mGradient 数据复制到新对象中。
    newG.mGradient = g1.mGradient;

    // 使用迭代器遍历 g2 的 mGradient 数据。
    auto g2It = g2.mGradient.begin();
    for (auto &i : newG.mGradient) {
        // 逐元素相加 g1 和 g2 中对应的浮点数值。
        i = i + *g2It;
        ++g2It; // 移动到下一个元素。
    }

    // 返回包含相加后数据的新对象。
    return newG;
}

inline Gradient::Data operator-(const Gradient::Data &g1,
                                const Gradient::Data &g2)
{
    if (g1.mGradient.size() != g2.mGradient.size()) return g1;
    Gradient::Data newG;
    newG.mGradient = g1.mGradient;

    auto g2It = g2.mGradient.begin();
    for (auto &i : newG.mGradient) {
        i = i - *g2It;
        g2It++;
    }

    return newG;
}

inline Gradient::Data operator*(float m, const Gradient::Data &g)
{
    Gradient::Data newG;
    newG.mGradient = g.mGradient;

    for (auto &i : newG.mGradient) {
        i = i * m;
    }
    return newG;
}

using ColorFilter = std::function<void(float &, float &, float &)>;

void configureModelCacheSize(size_t cacheSize);

std::shared_ptr<model::Composition> loadFromFile(const std::string &filePath,
                                                 bool cachePolicy);

std::shared_ptr<model::Composition> loadFromData(std::string        jsonData,
                                                 const std::string &key,
                                                 std::string resourcePath,
                                                 bool        cachePolicy);

std::shared_ptr<model::Composition> loadFromData(std::string jsonData,
                                                 std::string resourcePath,
                                                 ColorFilter filter);

std::shared_ptr<model::Composition> parse(char *str, size_t length, std::string dir_path,
                                          ColorFilter filter = {});

}  // namespace model

}  // namespace internal

}  // namespace rlottie

#endif  // LOTModel_H
